using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using viBook.Common;
using viBook.Models;

namespace viBook.Repositories
{
    public class ContentTagRepository : IContentTagRepository
    {
        private readonly viBookContext _context = new viBookContext();

        #region IContentTagRepository Members

        public IQueryable<ContentTag> All
        {
            get
            {
                IQueryable<ContentTag> result = _context.ContentTags;
                foreach (var contentTag in result)
                {
                    contentTag.NumberOfBook = _context.BookContentTags.Where(bct => bct.ContentTagId == contentTag.Id).Count();
                }
                return result;
            }
        }

        public ContentTag Find(int id)
        {
            var contentTag =  _context.ContentTags.Find(id);
            contentTag.NumberOfBook = _context.BookContentTags.Where(bct => bct.ContentTagId == contentTag.Id).Count();
            return contentTag;
        }

        public void Update(ContentTag contenttag)
        {
            if (contenttag.Id == default(int))
            {
                return;
            }
            _context.Entry(contenttag).State = EntityState.Modified;
            Save();
        }

        public void Insert(IEnumerable<ContentTag> contentTags)
        {
            foreach (ContentTag tag in contentTags)
            {
                bool found =
                    _context.ContentTags.Any(
                        c => c.ContentTagName.Equals(tag.ContentTagName, StringComparison.OrdinalIgnoreCase));
                if (!found)
                    _context.ContentTags.Add(tag);
            }
            Save();
        }

        public void InsertNew(ContentTag contentTags)
        {
            _context.ContentTags.Add(contentTags);
        }

        public bool Delete(int id)
        {
            ContentTag contenttag = FindContentTag(id);
            if (contenttag == null || contenttag.ListBook.Count() > 0)
            {
                return false;
            }
            _context.ContentTags.Remove(contenttag);
            Save();
            return true;
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public IEnumerable<string> FindContentTags(string s, int limit)
        {
            return _context.ContentTags.
                Where(c => c.ContentTagName.ToLower().Contains(s.ToLower())).
                Take(limit).
                Select(c => c.ContentTagName);
        }

        public int FindTagsByContent(string contenTag)
        {
            return _context.ContentTags.
                Where(c => c.ContentTagName.ToLower().Equals(contenTag.ToLower())).Select(c => c.Id).FirstOrDefault();
        }

        public ContentTag FindContentTag(int id)
        {
            var contentTag = _context.ContentTags.Find(id);
            if (contentTag != null)
            {
                var listIdBook = _context.BookContentTags.Where(bct => bct.ContentTagId == contentTag.Id).OrderBy(p => p.BookId).Select(bct => bct.BookId).ToList();
                var listBook = new List<Book>();
                foreach (int bookId in listIdBook)
                {
                    var book = _context.Books.Where(b => b.Id == bookId && b.IsBlocked==false).FirstOrDefault();
                    if (book != null)
                    {
                        book.Uploader = _context.Users.Where(u => u.Id == book.UploadedBy).FirstOrDefault();
                        if (book.Uploader != null)
                        {
                            book.UploaderName = book.Uploader.DisplayName;
                            book.UploaderAvartar = book.Uploader.AvatarUrl;

                        }
                        book.NumberOfLikes = _context.BookLikes.Where(bl => bl.BookId == book.Id).ToList().Count();
                        book.NumberOfComments = _context.BookComments.Where(bc => bc.BookId == book.Id).ToList().Count();
                        listBook.Add(book);
                    }
                }
                contentTag.ListBook = listBook;
            }
            return contentTag;
        }

        public IEnumerable<ContentTag> GetAllContentTagByBookId(int id)
        {
            List<int> listContentId =
                _context.BookContentTags.Where(bct => bct.BookId == id).Select(bct => bct.ContentTagId).ToList();
            var listContentTags = new List<ContentTag>();
            if (listContentId.Count > 0)
            {
                foreach (int contentId in listContentId)
                {
                    listContentTags.Add(Find(contentId));
                }
            }

            return listContentTags;
        }

        public IEnumerable<Book> FetchNextBookPage(int contentTagId, int pageNumber)
        {
            int skipItem = (pageNumber - 1) * Constant.MaximunItemsToPaging;
            var contentTagses = _context.BookContentTags.Where(bct => bct.ContentTagId == contentTagId).OrderBy(p => p.BookId).Skip(skipItem).Take(Constant.MaximunItemsToPaging).Distinct().ToList();
            var listBook = new List<Book>();
            foreach (var contentTag in contentTagses)
            {
                var book = _context.Books.Where(b => b.Id == contentTag.BookId).FirstOrDefault();
                if (book != null)
                {
                    book.Uploader = _context.Users.Where(u => u.Id == book.UploadedBy).FirstOrDefault();
                    if (book.Uploader != null)
                    {
                        book.UploaderName = book.Uploader.DisplayName;
                        book.UploaderAvartar = book.Uploader.AvatarUrl;

                    }
                    book.NumberOfLikes = _context.BookLikes.Where(bl => bl.BookId == book.Id).ToList().Count();
                    book.NumberOfComments = _context.BookComments.Where(bc => bc.BookId == book.Id).ToList().Count();
                    listBook.Add(book);
                }
            }
            return listBook;
        }

        public IEnumerable<ContentTag> GetMostPopularTags()
        {
            var listContentTag = _context.ContentTags.ToList();
            foreach (var contentTag in listContentTag)
            {
                if(contentTag!=null)
                contentTag.NumberOfBook =
                    _context.BookContentTags.Where(bct => bct.ContentTagId == contentTag.Id).Count();

            }
            return listContentTag.OrderByDescending(t => t.NumberOfBook).Take(Constant.NumberOfPopTags);
        }

        #endregion
    }

    public interface IContentTagRepository
    {
        IQueryable<ContentTag> All { get; }
        ContentTag Find(int id);
        void Update(ContentTag contenttag);
        void Insert(IEnumerable<ContentTag> contentTags);
        void InsertNew(ContentTag contentTags);
        bool Delete(int id);
        void Save();
        IEnumerable<string> FindContentTags(string s, int limit);
        int FindTagsByContent(string contenTag);
        ContentTag FindContentTag(int id);

        IEnumerable<ContentTag> GetAllContentTagByBookId(int id);
        IEnumerable<Book> FetchNextBookPage(int contentTagId, int pageNumber);
        IEnumerable<ContentTag> GetMostPopularTags();
    }
}
